Implement the JavaScript
Array.concat
function in the type system. A type takes the two arguments. The output should be a new array that includes inputs in ltr order
實現 JavaScript
中的 Array.concat
函數功能,並且在 TypeScript
的型別系統中完成這個功能。Concat
這個型別接收兩個陣列作為參數,並返回一個依次包含這兩個陣列元素的新陣列。
type Result = Concat<[1], [2]> // expected to be [1, 2]
接下來,你的任務是讓下面的type cases測試通過:
const tuple = [1] as const
type cases = [
Expect<Equal<Concat<[], []>, []>>,
Expect<Equal<Concat<[], [1]>, [1]>>,
Expect<Equal<Concat<typeof tuple, typeof tuple>, [1, 1]>>,
Expect<Equal<Concat<[1, 2], [3, 4]>, [1, 2, 3, 4]>>,
Expect<Equal<Concat<['1', 2, '3'], [false, boolean, '4']>, ['1', 2, '3', false, boolean, '4']>>,
]
未來補充😭
解法:
type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U];
細節分析:
Generic Parameters (泛型參數) <T extends readonly any[], U extends readonly any[]>
:
T extends readonly any[]
:T
是一個只讀的陣列(readonly
表示陣列中的元素不可修改),並且陣列元素的型別是 any
,即它可以包含任意型別的元素。extends 表示一個型別約束,這裡要求 T 必須是一個陣列。這確保了只能將符合陣列型別的資料傳入 T
。U extends readonly any[]
:T
相同,U
也是一個只讀的任意型別陣列。這個參數與 T
一起用來代表我們需要合併的第二個陣列。Spread Operator (展開運算符) ...T
和 ...U
:
...
T 和 ...U
是陣列展開運算符,在型別系統中,它會將陣列 T
和 U
中的所有元素解構並放入一個新的陣列。T
和 U
都展開,並合併成 [...]
,這就生成了一個包含 T
和 U
所有元素的新陣列。輸出型別:
Concat
型別的最終結果是一個新陣列型別,它會依次包含 T
和 U
中的所有元素,順序保持不變。 例如,Concat<[1, 2], [3, 4]>
的結果是 [1, 2, 3, 4]
。這樣,我們就能順利通過測試啦 🎉 😭 🎉
有沒有 readonly 實際上差在哪?
type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U];
// Example usage
const array1 = [1, 2] as const; // `as const` makes it readonly
const array2 = [3, 4] as const;
type Result = Concat<typeof array1, typeof array2>; // Result is inferred as [1, 2, 3, 4]
// Trying to modify array1 or array2 will cause an error
// array1[0] = 10; // Error: Cannot assign to '0' because it is a read-only property.
// array2.push(5); // Error: Property 'push' does not exist on type 'readonly [3, 4]'.
type Concat<T extends any[], U extends any[]> = [...T, ...U];
// Example usage
const array1 = [1, 2]; // Regular array
const array2 = [3, 4];
type Result = Concat<typeof array1, typeof array2>; // Result is inferred as [1, 2, 3, 4]
// Now we can modify array1 or array2 without errors
array1[0] = 10; // This is allowed; array1 is now [10, 2]
array2.push(5); // This is allowed; array2 is now [3, 4, 5]
console.log(array1); // Output: [10, 2]
console.log(array2); // Output: [3, 4, 5]
本次介紹了 Concat
的實作,下一關會挑戰 Includes
,期待再相見!